/* * This file provided by Facebook is for non-commercial testing and evaluation * purposes only. Facebook reserves all rights not expressly granted. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL * FACEBOOK BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ package com.facebook.samples.zoomable; import android.animation.Animator; import android.animation.AnimatorListenerAdapter; import android.animation.ValueAnimator; import android.annotation.SuppressLint; import android.graphics.Matrix; import android.support.annotation.Nullable; import android.view.animation.DecelerateInterpolator; import com.facebook.common.internal.Preconditions; import com.facebook.common.logging.FLog; import com.facebook.samples.gestures.TransformGestureDetector; /** * ZoomableController that adds animation capabilities to DefaultZoomableController using standard * Android animation classes */ public class AnimatedZoomableController extends AbstractAnimatedZoomableController { private static final Class<?> TAG = AnimatedZoomableController.class; private final ValueAnimator mValueAnimator; public static AnimatedZoomableController newInstance() { return new AnimatedZoomableController(TransformGestureDetector.newInstance()); } @SuppressLint("NewApi") public AnimatedZoomableController(TransformGestureDetector transformGestureDetector) { super(transformGestureDetector); mValueAnimator = ValueAnimator.ofFloat(0, 1); mValueAnimator.setInterpolator(new DecelerateInterpolator()); } @SuppressLint("NewApi") @Override public void setTransformAnimated( final Matrix newTransform, long durationMs, @Nullable final Runnable onAnimationComplete) { FLog.v(getLogTag(), "setTransformAnimated: duration %d ms", durationMs); stopAnimation(); Preconditions.checkArgument(durationMs > 0); Preconditions.checkState(!isAnimating()); setAnimating(true); mValueAnimator.setDuration(durationMs); getTransform().getValues(getStartValues()); newTransform.getValues(getStopValues()); mValueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator valueAnimator) { calculateInterpolation(getWorkingTransform(), (float) valueAnimator.getAnimatedValue()); AnimatedZoomableController.super.setTransform(getWorkingTransform()); } }); mValueAnimator.addListener(new AnimatorListenerAdapter() { @Override public void onAnimationCancel(Animator animation) { FLog.v(getLogTag(), "setTransformAnimated: animation cancelled"); onAnimationStopped(); } @Override public void onAnimationEnd(Animator animation) { FLog.v(getLogTag(), "setTransformAnimated: animation finished"); onAnimationStopped(); } private void onAnimationStopped() { if (onAnimationComplete != null) { onAnimationComplete.run(); } setAnimating(false); getDetector().restartGesture(); } }); mValueAnimator.start(); } @SuppressLint("NewApi") @Override public void stopAnimation() { if (!isAnimating()) { return; } FLog.v(getLogTag(), "stopAnimation"); mValueAnimator.cancel(); mValueAnimator.removeAllUpdateListeners(); mValueAnimator.removeAllListeners(); } @Override protected Class<?> getLogTag() { return TAG; } }